package com.godenwater.test;

import com.godenwater.core.spring.Application;
import com.godenwater.core.spring.BaseDao;
import com.godenwater.yanyu.utils.ByteUtil;
import com.godenwater.recv.model.CommonMessage;
import com.godenwater.recv.server.yln.YlnMessageHeader;
import com.godenwater.recv.service.AbstractMessageConsumer;
import com.godenwater.web.manager.StationDataManager;
import com.godenwater.web.manager.StationManager;
import com.godenwater.web.rtu.model.RtuStationData;
import com.godenwater.web.rtu.model.RtuStationModel;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import java.util.UUID;

/**
 * 1.1【亿立能】报文消费者
 * 
 * @ClassName: MessageConsumer
 * @Description: 通过线程的方式将“报文”解析，然后入库，这是消息进行处理的第一个环节
 * 
 *               注意：只启动一个消费者
 * @author lipujun
 * @date Mar 14, 2013
 * 
 */
public class MessageYlnConsumer2 extends AbstractMessageConsumer implements
		Runnable {

	private static Logger logger = LoggerFactory
			.getLogger(MessageYlnConsumer2.class);

	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

	private static long DAY = 24 * 60 * 60 * 1000;

	private static long HOUR = 60 * 60 * 1000;

	private static String KEY = "messages";

	private BaseDao dao = (BaseDao) Application.getInstance()
			.getBean("baseDao");

	public MessageYlnConsumer2() {

	}

	@Override
	public void run() {
		int i = 0;

	}

	/**
	 * 处理业务逻辑
	 *
	 * 第一步：原始报文入库
	 *
	 * 第二步：判断单报、多报。单报写“入库队列”；多报写文件，并根据最后一条报文写“合并队列”
	 *
	 * @param message
	 */
	public void process(String channel, CommonMessage message) throws Exception {
		logger.info("原始报文開始入庫！");

		boolean crcFlag = true;

		//IMessageHeader header = (IMessageHeader) message.getHeader();
		YlnMessageHeader header = (YlnMessageHeader) message
				.getHeader();
		byte[] funcCode = header.getSTART_BIT();
		//logger.info(">YLN DATA " + new String(funcCode) + new String(message.getContent()));

		// 解析报文体
		String funccode = new String(funcCode);
		String content = new String(message.getContent(),"GB2312");

		//实时数据
		//AAA;61079250;61079250;yilinengshuiwen;qipaoceshi;2017-03-10 15:00:00;1.61,12.2,0,0;水位(m),供电电压(V),环境温度(℃),水势;$END
		if (StringUtils.equalsIgnoreCase(funccode, "AAA")) {
			processRealData(content);
		}

		//密集数据
		if (StringUtils.equalsIgnoreCase(funccode, "BAA")) {
			processMijiData(message.getContent());
		}


	}

	/**
	 *根据实际的内容，将数据拆分并写入到数据库中
	 * @param content
	 */
	public void processRealData(String content){

		try {
			String[] msg = content.split(";");
			String stcd = msg[1];
			String viewtime = msg[5];
			String viewdata = msg[6];
			String viewnote = msg[7];
			logger.info(">YLN REAL DATA stcd " + stcd + " viewtime " + viewtime + " viewdata " + viewdata + " viewnote " + viewnote);

			String[] data = msg[6].split(",");
			String[] note = viewnote.split(",");

			stcd = convertStcd(stcd); //需要进行站码转换

			int dlen = data.length;
			int nlen = note.length;

			if (dlen == nlen) {
				//水位(m),供电电压(V),环境温度(℃),水势
				Date vd = sdf.parse(viewtime);
				for (int i = 0; i < nlen; i++) {
					if (note[i].indexOf("雨量") != -1) {

						RtuStationData oldData =  StationDataManager.getInstance().getStation(stcd);
						if(oldData == null){
							RtuStationData newData = new RtuStationData();
							newData.setStcd(stcd);
							newData.setRain5(data[i]);
							StationDataManager.getInstance().update(newData);
						}else{
							String orain = oldData.getRain5();

							BigDecimal b1 = new BigDecimal(data[i]);
							BigDecimal b2 = new BigDecimal(orain);

							oldData.setRain5(data[i]);
							StationDataManager.getInstance().update(oldData);
							//判断时间，根据时间的纬度来区分5分钟和小时
							String[] tm = viewtime.split(":");
							if(tm[1].equals("00")){
								System.out.println(">> tm 00 " );
							}else{
								System.out.println(">> tm " + tm[1]);
							}
							//writeYYConnvertData(stcd, vd, "1", 22, b1.subtract(b2).doubleValue(), 41);
						}
					}

					if (note[i].indexOf("水位") != -1) {
					    System.out.println("write 水位 data: stcd "+ stcd + " value " + Double.parseDouble(data[i]));
						//writeYYConnvertData(stcd, vd, "1", 11, Double.parseDouble(data[i]), 41);
					}

					if (note[i].indexOf("电压") != -1) {
						//writeYYConnvertData(stcd, vd, "1", 51, Double.parseDouble(data[i]), 41);
					}

				}
			}

			//原始报文入库
			String id = UUID.randomUUID().toString();
			String msgstr = "$AAA" +   content  ;
			//this.writeRtuMessage(id, stcd, "YLN", "",
			//		"AAA", 1,  sdf.parse(viewtime), 1, 1, msgstr,
			//		true);
		}catch (Exception e){
			e.printStackTrace();
		}
	}

	//处理密集型报文数据
	//4 + 4 + 4 + 16 + 2 + 1 + 1 + { 2 + 1 + 1 + 1 + 1 + 4×n }×m + 4
	//$BAA(4) 站号(4) 口令(4) 参数说明（16） 数据包总长（2） 时间间隔（1） 参数（1）
	//数据类型 { 2 + 1 + 1 + 1 + 1 + 4×n }
	//{ 年 月 日 时 分(参数1 参数2……参数n) }1
	//{ 年 月 日 时 分(参数1 参数2……参数n) }2
	//		………………………………………………
	//{ 年 月 日 时 分(参数1 参数2……参数n) }m
	//		$END
	public void processMijiData(byte[] buffer){
		int pos = 0;

		try {
			// 测站
			byte[] stcd = new byte[4];
			System.arraycopy(buffer, pos, stcd, 0, 4);
			pos = pos + 4;
			//ByteUtil.bytesToInt(stcd);
			String mStcd = convertStcd(""+ByteUtil.bytesToInt(new byte[]{stcd[3], stcd[2], stcd[1], stcd[0]})); //需要进行站码转换
			//System.out.println(">> stcd " + mStcd);
			// 口令
			byte[] pwd = new byte[4];
			System.arraycopy(buffer, pos, pwd, 0, 4);
			pos = pos + 4;

			// 说明
			byte[] note = new byte[16];
			System.arraycopy(buffer, pos, note, 0, 16);
			pos = pos + 16;
			//System.out.println(">> note " + new String(note));

			//数据包总长（2） 时间间隔（1） 参数（1）
			byte[] blen = new byte[2];
			System.arraycopy(buffer, pos, blen, 0, 2);
			pos = pos + 2;
			//System.out.println(">> 数据包总长 " + ByteUtil.bytesToShort(new byte[]{blen[1], blen[0]}));

			//时间间隔（1）
			byte[] sep = new byte[1];
			System.arraycopy(buffer, pos, sep, 0, 1);
			pos = pos + 1;
			//System.out.println(">> 时间间隔 " + ByteUtil.bytesToUbyte(sep));

			//参数（1）
			byte[] datatype = new byte[1];
			System.arraycopy(buffer, pos, datatype, 0, 1);
			pos = pos + 1;
			//ByteUtil.bytesToUbyte(param);
			//System.out.println(">> 参数数据类型 " + ByteUtil.bytesToUbyte(datatype));

			//获取时间
			byte[] year = new byte[2];
			System.arraycopy(buffer, pos, year, 0, 2);
			pos = pos + 2;
			ByteUtil.bytesToShort(year);
			byte[] month = new byte[1];
			System.arraycopy(buffer, pos, month, 0, 1);
			pos = pos + 1;
			//ByteUtil.bytesToUbyte(sep);
			byte[] day = new byte[1];
			System.arraycopy(buffer, pos, day, 0, 1);
			pos = pos + 1;
			byte[] hour = new byte[1];
			System.arraycopy(buffer, pos, hour, 0, 1);
			pos = pos + 1;
			//ByteUtil.bytesToUbyte(sep);
			byte[] minute = new byte[1];
			System.arraycopy(buffer, pos, minute, 0, 1);
			pos = pos + 1;
//ByteUtil.bytesToUbyte(sep);

			int nMonth = ByteUtil.bytesToUbyte(month);
			int nDay = ByteUtil.bytesToUbyte(day);
			int nHour =ByteUtil.bytesToUbyte(hour);
			int nMinute = ByteUtil.bytesToUbyte(minute);

			Date viewtime = sdf.parse(ByteUtil.bytesToShort(new byte[]{year[1], year[0]}) +"-"+ (nMonth<10?"0"+nMonth:nMonth) +"-" +(nDay<10?"0"+nDay:nDay)+" " + (nHour<10?"0"+nHour:nHour) +":" +(nMinute<10?"0"+nMinute:nMinute)+":00");
			DateTime dt = new DateTime(viewtime);
//System.out.println(">> 时间 " + ByteUtil.bytesToShort(new byte[]{year[1], year[0]}) + ByteUtil.bytesToUbyte(month) + ByteUtil.bytesToUbyte(day) + ByteUtil.bytesToUbyte(hour) + ByteUtil.bytesToUbyte(minute));
			logger.info(">YLN MIJI DATA stcd" + new String(stcd)+ "<" + mStcd  + ">  时间 " + sdf.format(viewtime )+" 时间间隔 " + ByteUtil.bytesToUbyte(sep) + "datatype " + ByteUtil.bytesToUbyte(datatype));

			dt = dt.minusHours(1).minusMinutes(dt.getMinuteOfHour());//将此数据标志为从前一小时开始的时间节点

			//长度/sep
			int dlen = 12;

			if (new String(note).indexOf("雨量") != -1) {
				for (int i = 0; i < dlen; i++) {
					dt = dt.plusMinutes(5);

					byte[] data = new byte[4];
					System.arraycopy(buffer, pos, data, 0, 4);
					pos = pos + 4;

					String rainValue = "0.0";
					if (datatype[0] == (byte) 0x1E) {//采用整形数据，加两位小数位，有正负之说
						BigInteger bi = new BigInteger(ByteUtil.toHexString(new byte[]{data[3], data[2], data[1], data[0]}), 16);
						//rainValue = bi.floatValue();
						DecimalFormat decimalFormat=new DecimalFormat(".00");//构造方法的字符格式这里如果小数不足2位,会以0补足.
						rainValue= decimalFormat.format(bi.intValue()/100);//format 返回的是字符串
						System.out.println(">> 0x1E rain data " + ByteUtil.toHexString(new byte[]{data[3], data[2], data[1], data[0]}) + " = " + bi.intValue() + " = " +rainValue);
					}

					if (datatype[0] == (byte) 0x00) {//采用浮点型数据类型，直接获取得到小数位
						Float value = Float.intBitsToFloat(new BigInteger(ByteUtil.toHexString(new byte[]{data[3], data[2], data[1], data[0]}), 16).intValue());
						//rainValue = value;
						DecimalFormat decimalFormat=new DecimalFormat(".00");//构造方法的字符格式这里如果小数不足2位,会以0补足.
						rainValue= decimalFormat.format(value);
						System.out.println(">> 0x00 rain data " + ByteUtil.toHexString(new byte[]{data[3], data[2], data[1], data[0]}) + " = " + value);
					}

					//下一步工作，就数据入库。
					if (new String(note).indexOf("雨量") != -1) {
						RtuStationData oldData =  StationDataManager.getInstance().getStation(mStcd);
						if(oldData == null){
							RtuStationData newData = new RtuStationData();
							newData.setStcd(mStcd);
							newData.setRain5(""+rainValue);
							StationDataManager.getInstance().update(newData);
						}else{
							String orain = oldData.getRain5();

							BigDecimal b1 = new BigDecimal(rainValue);
							BigDecimal b2 = new BigDecimal(orain);

							oldData.setRain5(""+rainValue);
							StationDataManager.getInstance().update(oldData);
							if(b1.subtract(b2).doubleValue() > 0 ) {
								//writeYYConnvertData(mStcd, dt.toDate(), "1", 23, b1.subtract(b2).doubleValue(), 41);
							}
						}
					}
				}
			}

			if (new String(note).indexOf("水位") != -1) {
				for (int i = 0; i < dlen; i++) {
					dt = dt.plusMinutes(5);

					byte[] data = new byte[4];
					System.arraycopy(buffer, pos, data, 0, 4);
					pos = pos + 4;

					if (datatype[0] == (byte) 0x1E) {//采用整形数据，加两位小数位，有正负之说
						BigInteger bi = new BigInteger(ByteUtil.toHexString(new byte[]{data[3], data[2], data[1], data[0]}), 16);
						System.out.println(">> 0x1E river data " + ByteUtil.toHexString(new byte[]{data[3], data[2], data[1], data[0]}) + " = " + bi.intValue());
						//writeYYConnvertData(mStcd,  dt.toDate(), "1", 11, bi.intValue(), 41);
					}

					if (datatype[0] == (byte) 0x00) {//采用浮点型数据类型，直接获取得到小数位
						Float value = Float.intBitsToFloat(new BigInteger(ByteUtil.toHexString(new byte[]{data[3], data[2], data[1], data[0]}), 16).intValue());
						System.out.println(">> 0x00 river data " + ByteUtil.toHexString(new byte[]{data[3], data[2], data[1], data[0]}) + " = " + value);
						//writeYYConnvertData(mStcd, dt.toDate(), "1", 11,value, 41);
					}
				}
			}

			//原始报文入库
			String id = UUID.randomUUID().toString();
			String msgstr = ByteUtil.toHexString("$BAA".getBytes()) +   ByteUtil.toHexString(buffer  );
			//this.writeRtuMessage(id, new String(stcd), "YLN", "",
			//		"BAA", 1,   viewtime, 1, 1, msgstr,
			//		true);
		}catch (Exception e){
			e.printStackTrace();
		}
		//int bodyLen = buffer.length - 4;
		//byte[] content = new byte[bodyLen];
		//System.arraycopy(buffer, pos, content, 0, bodyLen);
	}


	/**
	 * 亿立能的协议中，有一个测站的转换关系，针对荆州的测站编码对应关系，因站数太少，写在程序中
	 * @return
	 */
	public String convertStcd(String key){
		RtuStationModel station = StationManager.getInstance().getStation(key);

		if(station != null){
			return station.getStcd8();
		}else{
			//荆州测站
			Hashtable<String,String> table = new Hashtable();

			table.put("16121501","61058900");
			table.put("16121503","61056150");
			table.put("16121504","61057000");
			table.put("17030601","61015020");
			table.put("17031701","61520200");
			table.put("17031702","61521250");
			table.put("17032101","61015802");
			table.put("16011901","62213240");
			table.put("60975250","60975250");
			table.put("61077500","61077500");
			table.put("62165000","62165000");
			table.put("61079250","61079250");
			table.put("61074750","61074750");
			table.put("61500700","61500700");
			table.put("61007625","61007625");


			if(table.get(key)!=null){
				return table.get(key);
			}else{
				return "";
			}
		}


	}


	public static void main(String[] arg) {

		byte[] data = new byte[]{0x42,0x4e,0x00,0x00};
		Float value = Float.intBitsToFloat(new BigInteger("424e0000",16).intValue());
		System.out.println(">>. " + value.doubleValue() );

			BigDecimal b1 = new BigDecimal(Double.toString(1.01));
			BigDecimal b2 = new BigDecimal(Double.toString(1.0));
		System.out.println(">. " + b1.subtract(b2).doubleValue() );

		byte[] aaa = new byte[2];
		MessageYlnConsumer2 xxx = new MessageYlnConsumer2();

		String message = "7E7E0020320500FFFFFF4A800802000114061408373305ACB0";
		message = message.substring(0, 32);
		System.out.println(">. " + message);
		// //+ message.substring(44);
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String sendtime = "2014-06-17 11:00:00";
		Date send;
		try {
			send = sdf.parse(sendtime);

			Date now = new Date();

			long diff = now.getTime() - send.getTime();
			if (diff / HOUR > 6) {
				System.out.println(">>>>>" + diff / HOUR);
			}
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

}
